package org.xhy.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.xhy.security.filter.CodeCheckFilter;
import org.xhy.security.handler.MyAccessDeniedHandler;
import org.xhy.security.handler.MyAuthenticationFailureHandler;
import org.xhy.security.handler.MyAuthenticationSuccessHandler;
import org.xhy.security.mapper.PermissionMapper;
import org.xhy.security.service.MyUserDetailService;

import javax.sql.DataSource;


@Configuration // WebSecurityConfigurerAdapter :Security的配置类
@EnableWebSecurity //开启Security配置
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启方法授权注解支持
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Autowired
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private MyUserDetailService myUserDetailService;

    @Autowired
    private SmsAuthConfig smsAuthConfig;

//    //提供用户信息，这里没有从数据库查询用户信息，在内存中模拟
//    @Bean
//    public UserDetailsService userDetailsService(){
//        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
//        //创建用户，模拟数据库中的用户
//        inMemoryUserDetailsManager.createUser(User.withUsername("zs").password("123").authorities("admin").build());
//        return inMemoryUserDetailsManager;
//    }

    //密码编码器：加密
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

//    public static void main(String[] args) {
//        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
//        String encode = encoder.encode("123456");
//        System.out.println(encode); // $2a$10$uHcbYQijv9hzloKj0xztSejX4/./ipXpLTUxv760tKgR0j0rO7zxC
//
//        boolean matches = encoder.matches("123456", "$2a$10$uHcbYQijv9hzloKj0xztSejX4/./ipXpLTUxv760tKgR0j0rO7zxC");
//        System.out.println(matches);
//    }

    //授权规则配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {

//        List<Permission> permissions = permissionMapper.selectAll();
//        permissions.forEach(permission -> {
//            try {
//                http.authorizeRequests().antMatchers(permission.getResource()).hasAuthority(permission.getExpression());
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        });

        http.authorizeRequests()                                //授权配置
                .antMatchers("/login","/login.html","/sms/send/**").permitAll()  //登录路径放行
                .anyRequest().authenticated()                   //其他路径都要认证之后才能访问
                .and().formLogin()                              //允许表单登录
                .loginPage("/login.html")                       //指定自己的登陆页面
                .loginProcessingUrl("/login")                   //指定自己的数据提交路径
//                .successForwardUrl("/loginSuccess")           //设置登陆成功页
                .successHandler(myAuthenticationSuccessHandler) //设置自己的登陆成功页
                .failureHandler(myAuthenticationFailureHandler) //设置自己的登陆失败页
                .and().exceptionHandling().accessDeniedHandler(myAccessDeniedHandler).authenticationEntryPoint(myAccessDeniedHandler)  //设置自己的失败页
                .and().logout().permitAll()                     //登出路径放行 /logout
                .and().csrf().disable();                        //关闭跨域伪造检查

        http.rememberMe()
                .tokenRepository(tokenRepository())  //持久化
                .userDetailsService(myUserDetailService)  //用来加载用户认证信息的
                .tokenValiditySeconds(30000);   //设置过期时间

        //验证码检查的filter
        CodeCheckFilter smsCodeCheckFilter = new CodeCheckFilter();
        smsCodeCheckFilter.setMyAuthenticationFailureHandler(myAuthenticationFailureHandler);

        //添加验证码检查的filter
        http.addFilterBefore(smsCodeCheckFilter, UsernamePasswordAuthenticationFilter.class);

        //加入验证码的配置类
        http.apply(smsAuthConfig);
    }


    //记住我 持久化
    @Bean
    public PersistentTokenRepository tokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //tokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;

    }

}
